package com.gitee.loyo.act

import com.gitee.loyo.KSQL
import java.lang.reflect.ParameterizedType
import kotlin.reflect.KClass

open class Model<M: Model<M, R>, R: Record<M, R>>(
    tableName: String
): ModelSQLBuilder<M, R>(tableName), AggregateFunction by AggregateFunctionDelegate, SQLFunction by SQLFunctionDelegate {
    @delegate: Transient private val modelKClass: KClass<M> by lazy {
        ((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<M>).kotlin
    }
    @delegate: Transient internal val recordKClass: KClass<R> by lazy {
        ((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<R>).kotlin
    }
    @delegate: Transient internal val columns: List<Column<Any>> by lazy {
        KSQL.reflection.getClassParameters(this::class).map { KSQL.reflection.getFieldValue(this, it.name!!) as Column<Any> }
    }
    @delegate: Transient internal val primaryKeys: List<Column<Any>> by lazy {
        columns.filter { it.primaryKey != null }
    }

    open fun getPrimaryKey(): Column<Any> {
        if(primaryKeys == null || primaryKeys!!.isEmpty()){
            throw NullPointerException("没有发现主键，请用@PrimaryKey修饰${this::class.qualifiedName}的参数")
        }
        if(primaryKeys!!.size > 1){
            throw UnsupportedOperationException("主键有多个，请使用Model.getPrimaryKeys()或者Model.getPrimaryKey(String)")
        }
        return primaryKeys!!.first()
    }

    open fun getPrimaryKeys(): List<Column<Any>> {
        if(primaryKeys == null || primaryKeys!!.isEmpty()){
            throw NullPointerException("没有发现主键，请用@PrimaryKey修饰${this::class.qualifiedName}的参数")
        }
        return primaryKeys!!
    }

    open fun getPrimaryKey(columnName: String): Column<Any> {
        return getPrimaryKeys().first { it.columnName == columnName }
    }

    companion object{}
}